package android.serialport.sample;


import android.annotation.SuppressLint;
import android.os.SystemClock;
import android.serialport.SerialPort;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

public class TemperatureManager {

    private static String TAG = "#TemperatureManager";
    //    private static final byte[] OBJECT_TEMPERATURE_CMD = {0x4C, (byte) 0xAA, 0x55, 0x4B, 0x0D};
    private static final byte[] HUMAN_TEMPERATURE_CMD = {0x4E, (byte) 0xAA, 0x55, 0x4D, 0x0D};
    private static TemperatureManager mInstance;
    private InputStream mInputStream;
    private OutputStream mOutputStream;
    private SerialPort mSerialPort;
    private boolean isRunning = true;
    private TemperatureListener mListener;

    public static void init() {
        if (mInstance == null) {
            mInstance = new TemperatureManager();
        }
    }

    private TemperatureManager() {
        try {
            mSerialPort = getSerialPort();
            mInputStream = mSerialPort.getInputStream();
            mOutputStream = mSerialPort.getOutputStream();
            startTemperatureMonitor();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private SerialPort getSerialPort() throws IOException {
        if (mSerialPort == null) {

            SerialPort serialPort = SerialPort //
                .newBuilder("/dev/ttyS4", 19200) // 串口地址地址，波特率
                .parity(0) // 校验位；0:无校验位(NONE，默认)；1:奇校验位(ODD);2:偶校验位(EVEN)
                .dataBits(8) // 数据位,默认8；可选值为5~8
                .stopBits(1) // 停止位，默认1；1:1位停止位；2:2位停止位
                .build();

            mSerialPort = serialPort;
        }
        return mSerialPort;
    }

    private void closeSerialPort() {
        if (mSerialPort != null) {
            mSerialPort.close();
            mSerialPort = null;
        }
    }

//    byte[] objectTemperatureBuffer = new byte[5];
//                        mOutputStream.write(OBJECT_TEMPERATURE_CMD);
//                        SystemClock.sleep(100);
//    int objectTemperatureReadSize = mInputStream.read(objectTemperatureBuffer);
//double objectTemperature = -1;
//      if (objectTemperatureReadSize == 5 && checkValid(objectTemperatureBuffer)) {
//        objectTemperature = getTemperature(objectTemperatureBuffer);
//    }


    @SuppressLint("CheckResult")
    private void startTemperatureMonitor() {
        new Thread(new Runnable() {
            @Override
            public void run() {
                SystemClock.sleep(1000);
                while (isRunning) {
                    try {

                        byte[] humanTemperatureBuffer = new byte[5];
                        mOutputStream.write(HUMAN_TEMPERATURE_CMD);
                        SystemClock.sleep(50);
                        int humanTemperatureReadSize = mInputStream.read(humanTemperatureBuffer);

                        double humanTemperature = -1;

                        if (humanTemperatureReadSize == 5 && checkValid(humanTemperatureBuffer)) {
                            humanTemperature = getTemperature(humanTemperatureBuffer);
                        }
                        onChange(humanTemperature);
                        SystemClock.sleep(100);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }
        }).start();
    }

    private double getTemperature(byte[] data) {
        byte highData = data[1];
        byte lowData = data[2];
        String highDataBinary = getBinaryString(highData);
        String lowDataBinary = getBinaryString(lowData);
        float value = Integer.valueOf(highDataBinary + lowDataBinary, 2) * 1f;
        value = value / 16;
        value = value - 273.15f;
        return value;
    }

    private String getBinaryString(int data) {
        if (data < 0) {
            data += 256;
        }
        String lowDataBinaryStr = Integer.toBinaryString(data);
        int fillSize = 8 - lowDataBinaryStr.length();
        StringBuilder sb = new StringBuilder(lowDataBinaryStr);
        for (int i = 0; i < fillSize; i++) {
            sb.insert(0, "0");
        }
        return sb.toString();
    }

    private boolean checkValid(byte[] data) {
        int sumValue = 0;
        for (int i = 0; i <= 2; i++) {
            sumValue += data[i];
        }
        int checkSum = sumValue & 0xFF;
        int responseSum = data[3];
        if (responseSum < 0) {
            responseSum += 256;
        }
        return checkSum == responseSum && data[4] == 0x0D;
    }


    public static TemperatureManager getInstance() {
        return mInstance;
    }

    public synchronized void registerListener(TemperatureListener listener) {
        mListener = listener;
    }

    private synchronized void onChange(double humanTemperature) {
        if (mListener != null) {
            mListener.onChange(humanTemperature);
        }
    }

    public interface TemperatureListener {

        void onChange(double humanTemperature);
    }
}